home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Extensions… / UserItems ƒ / UserItems.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-20  |  10.7 KB  |  414 lines  |  [TEXT/MPS ]

  1. /*________________________________________________________
  2.  
  3.     File: UserItems.c
  4.  
  5.     C code for a printing extension that shows how
  6.     to handle hits and updates for userItems in panels.
  7.  
  8.     Dave Hersey
  9.     Apple Developer Technical Support
  10.  
  11.      6/06/93 - dmh - Created.
  12.      9/07/93 - dmh - Updated for b2.
  13.     12/18/93 - dmh - Updated for b3.
  14.      3/22/94 - dmh - Updated for b4.
  15.  
  16.     (Note: all functions are in the Mark menu.)
  17.     
  18. __________________________________________________________*/
  19.  
  20. #include "UserItems.h"
  21.  
  22.  
  23. MyGlobalRec        gl;        // Global data used by our extension.
  24.  
  25.  
  26. /*******************************************************************
  27.     InitGlobalData is used to initialize any global data we need to
  28.     in our initialize message override.  It's critical that you do
  29.     things this way, rather than access the data in the same scope
  30.     that you call NewMessageGlobals.  Otherwise, some compilers
  31.     will give you code that references an invalid a5 world.
  32.  
  33. ********************************************************************/
  34.  
  35. OSErr InitGlobalData()
  36. {
  37. // Initialize any global data here.
  38.     
  39.     gl.panelPict = nil;
  40.     return noErr;
  41. }
  42.  
  43.  
  44. /*******************************************************************
  45.     NewInitialize is our override for the Initialize message.  In
  46.     here, you shouldn't initialize anything directly-- call
  47.     InitGlobalData for that.  Once you create the A5 world with
  48.     NewMessageGlobals, you can access your global data just like
  49.     you were an app.  Whenever you're called, your global data will
  50.     be valid.
  51.     
  52. ********************************************************************/
  53.  
  54. OSErr NewInitialize()
  55. {
  56.     OSErr    err;
  57.  
  58. // Create an A5 world, and initialize our global data.
  59.  
  60.     err = NewMessageGlobals(A5Size(), A5Init);
  61.     
  62.     if (!err) err = InitGlobalData();
  63.     
  64.     return err;
  65. }
  66.  
  67.  
  68. /*******************************************************************
  69.     NewShutDown is our override for the GXShutDown message.  We
  70.     simply throw away our a5 world.
  71.     
  72. ********************************************************************/
  73.  
  74. OSErr NewShutDown()
  75. {
  76.     DisposeMessageGlobals();
  77.     return noErr;
  78. }
  79.  
  80.  
  81. /*******************************************************************
  82.     NewJobPrintDialog is our override for GXJobPrintDialog.  All
  83.     we do is set up our panel and then forward the message.
  84.     
  85. ********************************************************************/
  86.  
  87. OSErr NewJobPrintDialog(gxDialogResult *dlogResult)
  88. {
  89.     OSErr    err;
  90.     
  91.     err = SetUpPrintPanel();
  92.  
  93.     if (!err)
  94.         err = Forward_GXJobPrintDialog(dlogResult);
  95.     
  96.     return err;
  97. }
  98.  
  99.  
  100. /*******************************************************************
  101.     NewHandlePanelEvent is our override for GXHandlePanelEvent. If
  102.     the event is one of ours, we handle it, otherwise we just
  103.     forward it down the chain.
  104.     
  105. ********************************************************************/
  106.  
  107. OSErr NewHandlePanelEvent(gxPanelInfoRecord *panelInfo)
  108. {
  109.     OSErr            err = noErr;
  110.     GrafPtr            oldPort;
  111.     DialogPtr        pDlg;
  112.     short            oldResFile;
  113.  
  114. // Get a pointer to the dialog, save our current grafPort,
  115. // and set us to the dialog's port.
  116.  
  117.     pDlg = panelInfo->pDlg;
  118.     GetPort(&oldPort);
  119.     SetPort(pDlg);
  120.  
  121.     switch (panelInfo->panelEvt)
  122.     {
  123.         case gxPanelOpenEvt:            // Initialize and draw
  124.                                         // Load the user item picture.
  125.             oldResFile = CurResFile();
  126.             UseResFile(GXGetMessageHandlerResFile());
  127.             gl.panelPict = GetPicture(r_ExtensionPanel);
  128.             UseResFile(oldResFile);
  129.             break;
  130.  
  131.         case gxPanelCloseEvt:            // Your panel is going away (panel switch,
  132.                                         // confirm or cancel)
  133.             if (gl.panelPict)
  134.                 ReleaseResource((Handle) gl.panelPict);
  135.             
  136.             break;
  137.     }
  138.  
  139. // Restore the original port as we leave.
  140.  
  141.     SetPort(oldPort);
  142.     return err;
  143. }
  144.  
  145.  
  146. /*******************************************************************
  147.     NewFilterPanelEvent is a routine to filter update events in our
  148.     panel, and update our userItems accordingly.
  149.  
  150. ********************************************************************/
  151.  
  152. OSErr NewFilterPanelEvent(gxPanelInfoRecord *panelInfo, Boolean *returnImmed)
  153. {
  154.     OSErr        err = noErr;
  155.     DialogPtr    pDlg;
  156.     WindowPtr    theWindow;
  157.     short        thePart, theItem;
  158.     Point        thePt;
  159.  
  160. // Get a pointer to the dialog, save our current grafPort,
  161. // and set us to the dialog's port.
  162.  
  163.     pDlg = panelInfo->pDlg;
  164.  
  165.     switch (panelInfo->panelEvt)
  166.     {
  167.         case gxPanelFilterEvt:
  168.         
  169.             switch (panelInfo->theEvent->what)
  170.             {
  171.                 case updateEvt:        // look for, and handle, our update events.
  172.  
  173.                     if ((WindowPtr) panelInfo->theEvent->message == pDlg)
  174.                         err = HandlePanelUpdate(pDlg, panelInfo);
  175.  
  176.                     break;
  177.  
  178.                 case mouseDown:        // look for our dialog item hits.
  179.                                     // If we're not the front window, ignore hits.
  180.  
  181.                     require((pDlg == FrontWindow()), NotFrontWindow);
  182.                     thePart = FindWindow(panelInfo->theEvent->where, &theWindow);
  183.                     require(((theWindow == pDlg) && (thePart == inContent)), NotForUs);
  184.  
  185.                     thePt = panelInfo->theEvent->where;
  186.                     GlobalToLocal(&thePt);
  187.                     theItem = FindDItem(pDlg, thePt);
  188.  
  189.                                     // FindDItem == -1 if the point lies outside the dialog.
  190.                                     // Unless theItem == -1, go handle the hit.
  191.  
  192.                     if (theItem != -1)
  193.                         err = HandlePanelHit(pDlg, panelInfo, theItem +1, returnImmed);
  194.  
  195. NotForUs:
  196. NotFrontWindow:
  197.                     break;
  198.             }
  199.     }
  200.  
  201.     return err;
  202. }
  203.  
  204.  
  205. /*******************************************************************
  206.     HandlePanelUpdate is a routine to update our panel's userItems.
  207.     Note that we don't pass this routine to the Dialog Manager,
  208.     we only get here by way of our panel event handler.  This
  209.     assures that we can access our global data, and that our
  210.     resource file is open.  In this example, we draw from a global
  211.     PicHandle, to show that our globals are intact.
  212.     
  213.     NOTE: With the exception of the code below that's marked:
  214.     
  215.                "YOU SHOULD CHANGE THE FOLLOWING…"
  216.     
  217.     you can just use this code verbatim, regardless of the number
  218.     or purpose of your dialog's userItems.
  219.     
  220. ********************************************************************/
  221.  
  222. OSErr HandlePanelUpdate(DialogPtr theDialog, gxPanelInfoRecord *panelInfo)
  223. {
  224.     GrafPtr        oldPort;
  225.     OSErr        err;
  226.     Rect        theClipRect, myUserItemRect;
  227.     RgnHandle    tempRgn, oldVis;
  228.     Point        top;
  229.     short        dx, dy, itemKind;
  230.     Handle        itemHdl;
  231.  
  232. // Create a new region handle.  If we can't do that, return an error.
  233.  
  234.     tempRgn = NewRgn();
  235.     require_action(tempRgn, CanNotCreateRgn, err = MemError(););
  236.  
  237.  
  238. // Copy the window's update region to our temporary region handle,
  239. // then adjust the region so that it's correctly aligned with our
  240. // window.  Finally, intersect this region with the window's visRgn.
  241.  
  242.     CopyRgn(((DialogPeek) theDialog)->window.updateRgn, tempRgn);
  243.     top = *(Point *) &(*tempRgn)->rgnBBox.top;
  244.     GlobalToLocal(&top);
  245.     dx = (*tempRgn)->rgnBBox.left - top.h;
  246.     dy = (*tempRgn)->rgnBBox.top - top.v;
  247.     OffsetRgn(tempRgn, -dx, -dy);
  248.     SectRgn(theDialog->visRgn, tempRgn, tempRgn);
  249.  
  250.     nrequire((err = MemError()), CanNotCopyRgn);
  251.  
  252.  
  253. // Now, get the various bounds rects of your userItems and
  254. // see if any fall within the update area.  If not, don't
  255. // bother drawing anything.
  256. //
  257. // NOTE: YOU SHOULD CHANGE THE FOLLOWING CODE to account for
  258. // for all of your userItems.  We only have one userItem in
  259. // this example.
  260.  
  261.     GetDItem(theDialog, panelInfo->itemCount + kMyUserItem, &itemKind,
  262.              &itemHdl, &myUserItemRect);
  263.  
  264.     theClipRect = (*tempRgn)->rgnBBox;
  265.     
  266.     if (SectRect(&myUserItemRect, &theClipRect, &theClipRect))
  267.     {
  268.  
  269. // Save the current visRgn, and store our temporary region as the new
  270. // visRgn.  This is similar to what happens when BeginUpdate is called.
  271. // When we draw, only pixels that fall in the update area (clipped to
  272. // the window's clipRgn) will be drawn.  This keeps us from doing
  273. // unnecessary redrawing, which would cause flashing and wasted cycles.
  274.  
  275.         oldVis = theDialog->visRgn;
  276.         theDialog->visRgn = tempRgn;
  277.  
  278.  
  279. // Save the current port, change it to the dialog's port, draw any
  280. // userItems that need updating, validate their areas and restore
  281. // the old visRgn and grafPort.
  282. //
  283. // NOTE: YOU SHOULD CHANGE THE FOLLOWING CODE to redraw and validate
  284. // any of your userItems which intersect the update region.  We only
  285. // have one userItem in this example.
  286.  
  287.         GetPort(&oldPort);
  288.         SetPort(theDialog);
  289.  
  290.         DrawPicture(gl.panelPict, &myUserItemRect);
  291.         ValidRect(&myUserItemRect);
  292.                 
  293.         theDialog->visRgn = oldVis;
  294.         SetPort(oldPort);
  295.     }
  296.  
  297. // Throw away our temporary region, and return any error.
  298.  
  299. CanNotCopyRgn:
  300.     DisposeRgn(tempRgn);
  301.  
  302.  
  303. CanNotCreateRgn:
  304.     
  305.     return err;
  306. }
  307.  
  308.  
  309. /*******************************************************************
  310.     HandlePanelHit is a routine to handle mouse hits in a panel's
  311.     userItem fields.  In this sample, we simply invert our userItem
  312.     whenever it's clicked in, and set returnImmed to true,
  313.     indicating that this event has been processed.
  314.     
  315. ********************************************************************/
  316.  
  317. OSErr HandlePanelHit(DialogPtr theDialog, gxPanelInfoRecord *panelInfo,
  318.                      short theItem, Boolean *returnImmed)
  319. {
  320.     GrafPtr        oldPort;
  321.     OSErr        err = noErr;
  322.     short        itemKind;
  323.     Rect        itemRect;
  324.     Handle        itemHdl;
  325.  
  326. // Save the current grafPort, set the current port to the dialog,
  327. // handle our panel hits, and restore the current port.
  328.  
  329.     GetPort(&oldPort);
  330.     SetPort(theDialog);
  331.  
  332.     switch (theItem - panelInfo->itemCount)
  333.     {
  334.  
  335. // Flash our userItem if it's hit.
  336.  
  337.         case kMyUserItem:
  338.  
  339.             GetDItem(theDialog, theItem, &itemKind, &itemHdl, &itemRect);
  340.             InvertRect(&itemRect);
  341.             while (StillDown());
  342.             InvertRect(&itemRect);
  343.  
  344.             *returnImmed = true;
  345.             break;
  346.             
  347.         /*    Code for handling other userItems would follow.
  348.             .
  349.             .
  350.             .
  351.         */
  352.  
  353.     }
  354.  
  355.     SetPort(oldPort);
  356.     return err;
  357. }
  358.  
  359.  
  360. /*******************************************************************
  361.     SetUpPrintPanel sets up our print panel, adding a default
  362.     ExtensionCollection item to the job collection.  This
  363.     collection item has the values we'll use to set up our panel's
  364.     controls.
  365.     
  366. ********************************************************************/
  367.  
  368. OSErr SetUpPrintPanel()
  369. {
  370.     OSErr                    err;
  371.     gxPanelSetupRecord        panelSetupRec;
  372.     ExtensionCollection        extConfig;
  373.  
  374. // Try to find our collection item.
  375.  
  376.     err = GetCollectionItem(GXGetJobCollection(GXGetJob()),
  377.                             kExtensionCollectionType,
  378.                             gxPrintingTagID,
  379.                             nil,
  380.                             &extConfig);
  381.  
  382.  
  383. // If we don't have an item in the job collection yet, store our default
  384. // settings in it.
  385.  
  386.     if (err == collectionItemNotFoundErr)
  387.     {
  388.         extConfig.extTurnedOn = kDefaultSetting;
  389.     
  390.         err = AddCollectionItem(GXGetJobCollection(GXGetJob()),
  391.                                 kExtensionCollectionType,
  392.                                 gxPrintingTagID,
  393.                                 sizeof(ExtensionCollection),
  394.                                 &extConfig);
  395.  
  396.         nrequire(err, HaveCollectionMgrError);
  397.     }
  398.  
  399.  
  400. // Now, set up the panel.
  401.  
  402.     panelSetupRec.panelResId        = r_ExtensionPanel;        // which panel resource?
  403.     panelSetupRec.resourceRefNum    = GXGetMessageHandlerResFile(); // where is it?
  404.     panelSetupRec.refCon            = 0;                       // we don't use this.
  405.     panelSetupRec.panelKind            = gxExtensionPanel;     // This is an extension panel.
  406.  
  407.     err = GXSetupDialogPanel(&panelSetupRec);
  408.  
  409.  
  410. HaveCollectionMgrError:
  411.     
  412.     return err;
  413. }
  414.